<?php

class Application_Model_PagamentoAposta
{
    private $_pagamento;

    private $_total_bolitos = 100;

    public function __construct() {
        $this->_pagamento = new Application_Model_UsuarioMapper();
    }

    function iniciaTrasacao()
    {
        $this->_pagamento->iniciaTrasacao();
    }

    function desfazer()
    {
        $this->_pagamento->desfazer();
    }

    function finalizaTransacao()
    {
        $this->_pagamento->finalizaTrasacao();
    }

    public function getVencedores($id_bolao, $jogo) {

        $aposta = new Application_Model_ApostaMapper();
        $bolao = new Application_Model_BolaoMapper();

        $id_jogo = $jogo->getId();

        //captura todos os apostadores desse bolao.
        $apostadores = $aposta->localizarApostaBolao($id_bolao);

        $this->_total_bolitos = count($apostadores)*5;

        //echo var_export($apostadores);

        $pontuacao = $this->calculaPontuacao($apostadores, $jogo);

        arsort($pontuacao);

        //Verifica ate qual posicao tera ganhadores.
        $posicao = $this->calculaNumeroDeVencedores(count($pontuacao));

        $pre_vencedores = $this->calculaPreVencedores($pontuacao, $posicao);

        $pre_vencedores = $this->desempata($pre_vencedores, $id_jogo, $id_bolao, $jogo);

        arsort($pre_vencedores);

        $vencedores = $this->calculaVencedores($pre_vencedores, $posicao);

        $vencedores1 = $this->calculaQuantidadesDeBolitos($vencedores);

        
        $ganha = array();

        //Insere na tabela todos os bolitos dos ganhadores.
        $lista_vencedores = array_keys($vencedores1);

        foreach($lista_vencedores as $email) {

            $ganha[] = array(
                        0 => $email,
                        1 => ($vencedores1[$email]/100.0)
                    );
        }

        return $ganha;

    }

    public function getApostadores($id_bolao, $id_jogo) {

        $aposta = new Application_Model_ApostasAbertasMapper();

        $apostadores = $aposta->getApostadores($id_bolao, $id_jogo);

        $ganha = array();

        foreach($apostadores as $email) {

            $ganha[] = array(
                        0 => $email->email_usuario,
                        1 => 'Não definido.'
                    );
        }

        return $ganha;

    }



    /**
     * Efetua o pagamento de um determinado jogo a todos os usuarios que apostaram.
     * @param Application_Model_Jogo $jogo
     */
    function efetuaPagamento(Application_Model_Jogo $jogo)
    {       

        $aposta = new Application_Model_ApostaMapper();
        $bolao = new Application_Model_BolaoMapper();

        $id_jogo = $jogo->getId();

        //captura todos os boloes que esta na aspota desse jogo.
        $boloes = $aposta->localizarAposta($id_jogo); 

        //para todos os boloes...
        foreach ($boloes as $linha_bolao)
        {
            $id_bolao = $linha_bolao->id_bolao;
            
            //captura todos os apostadores desse bolao.
            $apostadores = $aposta->localizarApostaBolao($id_bolao);

            $this->_total_bolitos = count($apostadores)*5;

            //echo var_export($apostadores);

            $pontuacao = $this->calculaPontuacao($apostadores, $jogo);

            arsort($pontuacao);

            //Verifica ate qual posicao tera ganhadores.
            $posicao = $this->calculaNumeroDeVencedores(count($pontuacao));

            $pre_vencedores = $this->calculaPreVencedores($pontuacao, $posicao);
            
            $pre_vencedores = $this->desempata($pre_vencedores, $id_jogo, $id_bolao, $jogo);

            arsort($pre_vencedores);

            $vencedores = $this->calculaVencedores($pre_vencedores, $posicao);

            $vencedores1 = $this->calculaQuantidadesDeBolitos($vencedores);

            //Insere na tabela todos os bolitos dos ganhadores.
            $lista_vencedores = array_keys($vencedores1);
            
            foreach($lista_vencedores as $email)
            {

                $this->_pagamento->inserirBolitos($email, $vencedores1[$email]);
            }

            $this->recarregaBolitos($apostadores, $vencedores1);
            
            $pontuacao = null;
            $pre_vencedores = null;
            $vencedores = null;
            $vencedores1 = null;

        }

    }

    /**
     *
     * @param <type> $apostadores lista de todos os apostadores.
     * @return <type> Array contendo todos os apostadores com suas respectvas pontuacoes.
     */
    private static function calculaPontuacao($apostadores, $jogo)
    {
        foreach ($apostadores as $linha_apostadores)
        {
            $pontuacao[$linha_apostadores->email_usuario] = 0;

            if($linha_apostadores->gols_time_a == $jogo->getGolsTimeA() &&
                    $linha_apostadores->gols_time_b == $jogo->getGolsTimeB()) {
                $pontuacao[$linha_apostadores->email_usuario] += 8;
            }

            if($linha_apostadores->placar_parcial == $jogo->getPlacarParcial()) {
                $pontuacao[$linha_apostadores->email_usuario] += 4;
            }

            $time_vencedor_jogo = ($jogo->getGolsTimeA() >= $jogo->getGolsTimeB()) ? 0 : 1;
            $time_vencedor_apostador = ($linha_apostadores->gols_time_a >= $linha_apostadores->gols_time_b) ? 0 : 1;

            $empate_jogo = ($jogo->getGolsTimeA() == $jogo->getGolsTimeB()) ? 0 : 1;
            $time_empate_apostador = ($linha_apostadores->gols_time_a == $linha_apostadores->gols_time_b) ? 0 : 1;

            if(($time_vencedor_jogo == $time_vencedor_apostador) && ($empate_jogo == $time_empate_apostador)) {
                $pontuacao[$linha_apostadores->email_usuario] += 2;
            }

            if(($jogo->getGolsTimeA() + $jogo->getGolsTimeB()) ==
                    ($linha_apostadores->gols_time_a + $linha_apostadores->gols_time_b)) {
                $pontuacao[$linha_apostadores->email_usuario] += 1;
            }
        }

        return $pontuacao;
    }

    /**
     *
     * @param <type> $quantidade_apostadores
     * @return <type> Posicao maxima que tera ganhador.
     */
    private static function calculaNumeroDeVencedores($quantidade_apostadores)
    {
        if($quantidade_apostadores <= 4)
            return 1;
        if($quantidade_apostadores <= 7)
            return 2;
        if($quantidade_apostadores <= 11)
            return 3;
        if($quantidade_apostadores <= 15)
            return 4;
        if($quantidade_apostadores <= 25)
            return 5;

        $valor = ceil((($quantidade_apostadores / 25) + 4));
        return $valor;
    }

    /**
     *
     * @param <type> $pontuacao array com os apostadores e sua pontuacao.
     * @param <type> $posicao
     * @return <type> Array contendo todos os posiveis ganhadores.
     */
    private static function calculaPreVencedores($pontuacao, $posicao)
    {
        $cont = 0;
        $pontuacao_anterior = 0;

        $chaves = array_keys($pontuacao);
        foreach($chaves as $email)
        {
            if(($cont >= $posicao) && ($pontuacao[$email] < $pontuacao_anterior))
            {
                break;
            }

            $pre_vencedores[$email] = $pontuacao[$email];
            $pontuacao_anterior = $pontuacao[$email];
            $cont++;
        }

        return $pre_vencedores;
    }

    /**
     * Faz o desmpate dos apostadores de acordo com a ordem de gols.
     * 
     * @param <type> $pre_vencedores
     * @param <type> $id_jogo
     * @param <type> $id_bolao
     * @return <type> Lista dos postadores com sua pontuacao apos aplicado o criterio de desempate.
     */
    private function desempata($pre_vencedores, $id_jogo, $id_bolao, $jogo)
    {
        $aposta = new Application_Model_ApostaMapper();

        $chaves = array_keys($pre_vencedores);

        $cont = 0;

        foreach($chaves as $email)
        {
            $mudanca = $pre_vencedores[$email];
            break;
        }

        foreach($chaves as $email)
        {
            $ordem = $aposta->localizarOrdemDeGols($email, $id_jogo, $id_bolao);
            $ordem = str_replace('C', '', $ordem);

            $ordem1 = $jogo->getOrdemGols();
            $ordem1 = str_replace('C', '', $ordem1);

            $aux = $pre_vencedores[$email];

            if($ordem1 == $ordem) {
                $pre_vencedores[$email] -= ($cont);
            }
            else {
                $pre_vencedores[$email] -= $cont + 1;
            }

            if($aux != $mudanca) {
                $cont++;
                $mudanca = $aux;
            }
        }

        return $pre_vencedores;
    }

    /**
     *
     * @param <type> $pre_vencedores
     * @return <type> Recria a lista com os ganhadores definidos.
     */
    private function calculaVencedores($pre_vencedores, $posicao)
    {
        $chaves = array_keys($pre_vencedores);

        $cont = 0;
        $pontuacao_anterior = 0;

        foreach($chaves as $email)
        {
            if(($cont >= $posicao) && ($pre_vencedores[$email] < $pontuacao_anterior)) {
                break;
            }

            $vencedores[$email] = $pre_vencedores[$email];
            $pontuacao_anterior = $pre_vencedores[$email];
            $cont++;
        }

        return $vencedores;
    }

    /**
     *
     * @param <type> $vencedores
     * @return <type> Lista dos vencedores com o numero de bolitos de cada.
     */
    private function calculaQuantidadesDeBolitos($vencedores)
    {       

        $apostadores_ganhadores = count($vencedores);

        $chaves = array_keys($vencedores);

        $cont = 0;
        $pontuacao_anterior = 0;

        foreach($chaves as $email) {
            $mudanca = $vencedores[$email];
            break;
        }

        $peso = 0;

        foreach($chaves as $email)
        {
            $aux = $vencedores[$email];

            if($aux == $mudanca)
            {
                $peso += $apostadores_ganhadores;
                $vencedores[$email] = $apostadores_ganhadores;
            }
            else
            {
                $mudanca = $aux;
                $vencedores[$email] = $apostadores_ganhadores - $cont;
                $apostadores_ganhadores -= $cont;
                $peso += $apostadores_ganhadores;
            }

            $cont++;
        }

        foreach($chaves as $email)
        {
            $vencedores[$email] = round(($vencedores[$email]/$peso)*$this->_total_bolitos*100);
        }

        return $vencedores;
    }

    public function recarregaBolitos($apostadores, $vencedores1)
    {
        $aposta = new Application_Model_ApostasAbertasMapper();

        $total_bolitos = 100;

        foreach ($apostadores as $linha_apostadores)
        {
            $existe = array_key_exists($linha_apostadores->email_usuario, $vencedores1);
            if(!$existe)
            {
                $bolitos = $this->_pagamento->getBolitos($linha_apostadores->email_usuario);

                $numeroApostas = $aposta->getApostasAbertas($linha_apostadores->email_usuario);
                $bolitosRecarga = $total_bolitos*80;

                if(($bolitos < 500) && ($numeroApostas == 1))
                {
                    $this->_pagamento->recarregarBolitos($linha_apostadores->email_usuario, $bolitosRecarga);
                }
            }
        }
    }
}
